<script setup>
import TaskEdit from '@/views/liteflow/task/taskEdit.vue'
import TaskLogList from '@/views/liteflow/task/taskLogList.vue'
import Codemirror from "codemirror-editor-vue3"
import "codemirror/mode/clike/clike"
import "codemirror/mode/javascript/javascript"
import "codemirror/mode/php/php"
import "codemirror/mode/powershell/powershell"
import "codemirror/mode/python/python"
import "codemirror/mode/shell/shell"
import { ref, watch } from 'vue'
import { VDataTableServer } from 'vuetify/labs/VDataTable'

// 表头
const headers = [
  {
    title: '任务ID',
    key: 'id',
  },
  {
    title: '任务名称',
    key: 'jobDesc',
  },
  {
    title: '任务执行器',
    key: 'jobGroup',
  },
  {
    title: '调度类型',
    key: 'scheduleType',
  },
  {
    title: '运行模式',
    key: 'glueType',
  },
  {
    title: '负责人',
    key: 'author',
  },
  {
    title: '状态',
    key: 'triggerStatus',
  },
  {
    title: '操作',
    key: 'actions',
    sortable: false,
  },
]

const pageUrl = ref(API_URLS.xxljobTaskPage)
const deleteUrl = ref(API_URLS.xxljobTaskDelete)
const addUrl = ref(API_URLS.xxljobTaskAdd)
const updateUrl = ref(API_URLS.xxljobTaskUpdate)
const id = ref()
const jobDesc = ref()
const jobGroup = ref()
const triggerStatus = ref()
const executorHandler = ref()
const author = ref()

// 代码编辑器
const cmRef = ref()

const cmOptions = {
  mode: "text/x-java",
}

const onChange = (val, cm) => {
  //console.log(val)
  //console.log(cm.getValue())
}

const onInput = val => {
  //console.log(val)
}

const onReady = cm => {
  //console.log(cm.focus())
}

onMounted(() => {
  optionSelect()
  jobGroupOptionSelect()

  setTimeout(() => {
    cmRef.value?.refresh()
  }, 1000)
})

onUnmounted(() => {
  cmRef.value?.destroy()
})

const jobGroupOption = reactive([])

const jobGroupOptionSelect = async () => {
  const res = await $ivyApi.post(API_URLS.xxljobGroupOptions,{ })
  jobGroupOption.push(...res.data)
}

const option = reactive({
  scheduleType: {
    label: '',
    list: [],
  },
  glueType: {
    label: '',
    list: [],
  },
  executorRouteStrategy: {
    label: '',
    list: [],
  },
  misfireStrategy: {
    label: '',
    list: [],
  },
  executorBlockStrategy: {
    label: '',
    list: [],
  },
})

const optionSelect = async () => {
  const res = await $ivyApi.post(API_URLS.xxljobTaskOption,{ fieldNames: 'scheduleType,glueType,executorRouteStrategy,misfireStrategy,executorBlockStrategy' })
  Object.assign(option, res.data)
}

// 分页列表
const totalPage = ref(1)
const totalRows = ref(0)
const list = ref([])
const loadings = ref(false)

// 分页参数
const options = ref({
  page: 1,
  itemsPerPage: 10,
  sortBy: [],
  groupBy: [],
  search: undefined,
})

const fetchList = async (msg) => {
  loadings.value = true
  const res = await $ivyApi.post(pageUrl.value,{
    id: id.value,
    jobDesc: jobDesc.value,
    jobGroup: jobGroup.value,
    triggerStatus: triggerStatus.value,
    executorHandler: executorHandler.value,
    author: author.value,
    options: options.value,
  })
  
  const data = res.data
  list.value = data.list
  totalPage.value = data.totalPage
  totalRows.value = data.totalRow
  options.value.page = data.page
  loadings.value = false

  if(typeof msg === 'string'){
    res.message = msg
    showMsg(res)
  }
}

watchEffect(fetchList)
// 监听 options 对象的变化，并在变化时调用 fetchList 方法
watch(options, async () => { await fetchList() }, { deep: true })

// 新增&编辑操作
const currRow = ref({})
	
const addOper = () => {
  currRow.value = {}
  editVisible.value = true
}

const updateOper = row => {
  currRow.value = row
  editVisible.value = true
}

const editVisible = ref(false)
const editRef = ref(null)

const editCallMethod = () => {
  // editVisible.value = false
  editRef.value.saveItem()
}

const closeEditDialog = valid => {
  if(valid){
    editVisible.value = false
  }else{
    editVisible.value = true
  }
}

const editCancelMethod = () =>{
  editVisible.value = false
}

const refreshPage = res => {
  showMsg(res)
  fetchList()
}

// 查看
const viewOper = row => {
  currRow.value = row
}


// 删除
const deleteId = ref('')
const deleteVisible = ref(false)

const deleteOper = id => {
  deleteVisible.value = true
  deleteId.value = id
}

// 确认删除
const deleteAgreeCmp = async (id) => {
  const res = await $ivyApi.post(deleteUrl.value,{
    id: deleteId.value,
  })

  showMsg(res)
  fetchList()
  deleteVisible.value = false
  deleteId.value = ''
}

// 任务开始
const startId = ref('')
const startVisible = ref(false)

const startOper = id => {
  startVisible.value = true
  startId.value = id
}

// 确认任务开始
const startAgreeCmp = async (id) => {
  const res = await $ivyApi.post(API_URLS.xxljobTaskStart,{
    id: startId.value,
  })
  startVisible.value = false
  startId.value = ''
  refreshPage(res)
}


// 任务结束
const stopId = ref('')
const stopVisible = ref(false)

const stopOper = id => {
  stopVisible.value = true
  stopId.value = id
}

// 确认任务结束
const stopAgreeCmp = async (id) => {
  const res = await $ivyApi.post(API_URLS.xxljobTaskStop,{
    id: stopId.value,
  })
  stopVisible.value = false
  stopId.value = ''
  refreshPage(res)
}

// 回调信息
const snackbar = reactive(API_URLS.resultMsg)

const showMsg = res => {
  $resultMsg.show(res,snackbar)
}


const triggerStatusOption = [
  { color: 'error', title: '已停止', value: 0 },
  { color: 'success', title: '运行中', value: 1 },
]

const resolveStatusVariant = status => {
  return triggerStatusOption.filter(obj => obj.value == status)[0]
}

const resolveGlueTypeVariant = value => {
  return option.glueType.list.filter(obj => obj.value == value)[0]
}

// 操作菜单
const menuList = reactive([])

const getMenus = row => {
  menuList.length = 0

  const glueType = row.glueType
  const triggerStatus = row.triggerStatus

  const menus = []

  menus.push({ title: '执行一次', value: 0, row: row })
  menus.push({ title: '查询日志', value: 1, row: row })
  if(glueType != 'BEAN' && glueType != 'LITE_FLOW'){
    menus.push({ type: 'divider' })
    menus.push({ title: 'GLUE IDE', value: 2, row: row })
  }
  
  menus.push({ type: 'divider' })
  if(triggerStatus == 0){
    menus.push({ title: '启动', value: 3, row: row })
  }else{
    menus.push({ title: '停止', value: 4, row: row })
  }
  
  menus.push({ title: '编辑', value: 6, row: row })
  menus.push({ title: '删除', value: 7, row: row })
  menus.push({ title: '复制', value: 8, row: row })

  menuList.push(...menus)

  return menus
}

const codeVisible = ref(false)
const logVisible = ref(false)
const execOneVisible = ref(false)
const executorParam = ref()
const addressList = ref()
const codeVersion = ref()
const codeVersions = reactive([])
const glueSource = ref()
const glueRemark = ref()

watch(codeVersion, val => {
  glueSource.value = val
})

const operClick = async (obj) => {
  const id = obj.id
  const filterMenu = menuList.filter(item => item.value !== id)[0]

  currRow.value = JSON.parse(JSON.stringify(filterMenu.row))

  if(id == 0){
    execOneVisible.value = true
  }else if(id == 1){
    logVisible.value = true
  }else if(id == 2){
    const r = await $ivyApi.post(API_URLS.xxljobTaskCodeInit,currRow.value)
    const res = r.data

    glueSource.value = res.glueSource
    glueRemark.value = res.glueRemark
    codeVersions.length = 0
    codeVersions.push(...res.xxlJobLogGlueList)
    cmRef.value?.refresh()

    const glueType = currRow.value.glueType
    if('GLUE_GROOVY' == glueType){
      cmOptions.mode = 'text/x-java'
    }else if('GLUE_SHELL' == glueType){
      cmOptions.mode = 'text/x-sh'
    }else if('GLUE_PYTHON' == glueType){
      cmOptions.mode = 'text/x-python'
    }else if('GLUE_PHP' == glueType){
      cmOptions.mode = 'text/x-php'
    }else if('GLUE_NODEJS' == glueType){
      cmOptions.mode = 'text/javascript'
    }else if('GLUE_POWERSHELL' == glueType){
      cmOptions.mode = 'powershell'
    }

    codeVisible.value = true
  }else if(id == 3){//启动
    startOper(currRow.value.id)
  }else if(id == 4){//停止
    stopOper(currRow.value.id)
  }else if(id == 6){
    editVisible.value = true
  }else if(id == 7){
    deleteOper(currRow.value.id)
  }else if(id == 8){
    currRow.value.id = null
    editVisible.value = true
  }
}

const codeInitClick = async () => {
  const res = await $ivyApi.post(API_URLS.xxljobTaskCodeRefresh,currRow.value)
  glueSource.value = res.data.glueSource
  cmRef.value?.refresh()
}

const codeClick = async () => {
  codeVisible.value = false
  const res = await $ivyApi.post(API_URLS.xxljobTaskCode,{
    id: currRow.value.id,
    glueSource: glueSource.value,
    glueRemark: glueRemark.value,
  })
  refreshPage(res)
}

const execOneClick = async () => {
  execOneVisible.value = false
  const res = await $ivyApi.post(API_URLS.xxljobTaskTrigger,{
    id: currRow.value.id,
    executorParam: executorParam.value,
    addressList: addressList.value,
  })
  refreshPage(res)
}

const getSubstrings = str => {
  return str ? str.split(',') : []
}

const nextTriggerTimes = reactive([])
const isSnackbarVisibility = ref(false)

const getNextTriggerTimes = async (scheduleType, scheduleConf) => {
  nextTriggerTimes.length = 0
  const res = await $ivyApi.post(API_URLS.xxljobTaskNextTriggerTime,{
    scheduleType: scheduleType,
    scheduleConf: scheduleConf,
  })
  nextTriggerTimes.push(...res.data)
  isSnackbarVisibility.value = true
}

</script>

<template>
  <section>
    <VRow>
      <VSnackbar
        v-model="snackbar.msgVisible"
        location="top"
        :color="snackbar.msgColor"
      >
        {{ snackbar.msgContent }}
      </VSnackbar>

      <VSnackbar
        v-model="isSnackbarVisibility"
        min-width="100px"
      >
        <span>下次执行时间：<br></span>
        <span
          v-for="(time, index) in nextTriggerTimes"
          :key="index"
        >{{ time }}<br></span>
        
        <template #actions>
          <VBtn
            color="error"
            @click="isSnackbarVisibility = false"
          >
            关闭
          </VBtn>
        </template>
      </VSnackbar>

      <VCol cols="12">
        <VCard title="">
          <VCardText>
            <VRow>
              <VCol
                cols="12"
                sm="4"
              >
                <VTextField
                  v-model="id"
                  label="任务ID"
                  clearable
                />
              </VCol>
              <VCol
                cols="12"
                sm="4"
              >
                <VTextField
                  v-model="jobDesc"
                  label="任务名称"
                  clearable
                />
              </VCol>
              <VCol
                cols="12"
                sm="4"
              >
                <VSelect
                  v-model="jobGroup"
                  label="任务执行器"
                  :items="jobGroupOption"
                  clearable
                  item-title="title"
                  item-value="id"
                />
              </VCol>
              <VCol
                cols="12"
                sm="4"
              >
                <VTextField
                  v-model="executorHandler"
                  label="JobHandler"
                  clearable
                />
              </VCol>
              <VCol
                cols="12"
                sm="4"
              >
                <VTextField
                  v-model="author"
                  label="负责人"
                  clearable
                />
              </VCol>
              <VCol
                cols="12"
                sm="4"
              >
                <VAutocomplete
                  v-model="triggerStatus"
                  label="状态"
                  :items="triggerStatusOption"
                  clearable
                />
              </VCol>
            </VRow>
          </VCardText>

          <VDivider />

          <VCardText class="d-flex flex-wrap py-4 gap-4">
            <div class="me-3 d-flex gap-3">
              <AppSelect
                :model-value="options.itemsPerPage"
                :items="[
                  { value: 10, title: '10' },
                  { value: 20, title: '20' },
                  { value: 50, title: '50' },
                  { value: 100, title: '100' },
                ]"
                style="inline-size: 6.25rem;"
                @update:model-value="options.itemsPerPage = parseInt($event, 10)"
              />
            </div>
            <VSpacer />

            <div class="d-flex align-center flex-wrap gap-4">
              <VBtn
                :loading="loadings"
                :disabled="loadings"
                size="38"
                @click="fetchList('刷新成功')"
              >
                <VIcon
                  icon="tabler-refresh"
                  size="22"
                />
                <VTooltip
                  activator="parent"
                  location="top"
                >
                  刷新
                </VTooltip>
              </VBtn>
              <VBtn
                prepend-icon="tabler-plus"
                @click="addOper"
              >
                新增任务
              </VBtn>
            </div>
          </VCardText>

          <VDivider />

          <VDataTableServer
            v-model:items-per-page="options.itemsPerPage"
            v-model:page="options.page"
            :items="list"
            :items-length="totalRows"
            :headers="headers"
            class="text-no-wrap"
            @update:options="options = $event"
          >
            <template #item.id="{ item }">
              <span class="font-weight-medium">{{ item.id }}</span>
            </template>

            <template #item.jobDesc="{ item }">
              <span class="font-weight-medium">{{ item.jobDesc }}</span>
            </template>

            <template #item.jobGroup="{ item }">
              <span class="font-weight-medium">
                <VBtn
                  variant="plain"
                  size="small"
                  style="padding-inline-start: 0;"
                >
                  {{ item.jobGroup }}
                  <VTooltip
                    activator="parent"
                    location="top"
                  >
                    <span>任务执行器：{{ item.xxlJobGroup.title }}<br></span>
                    <span>注册的节点：<br></span>
                    <span
                      v-for="(substring, index) in getSubstrings(item.xxlJobGroup.addressList)"
                      :key="index"
                    >{{ substring }}<br></span>
                  </VTooltip>
                </VBtn>
              </span>
            </template>

            <template #item.scheduleType="{ item }">
              <span class="font-weight-medium">
                
                <VBtn
                  variant="plain"
                  size="small"
                  style="padding-inline-start: 0;"
                  @click="getNextTriggerTimes(item.scheduleType,item.scheduleConf)"
                >
                  {{ item.scheduleType +"："+ item.scheduleConf }}
                </VBtn>
              </span>
            </template>

            <template #item.glueType="{ item }">
              <span
                v-if="item.glueType == 'BEAN' || item.glueType == 'LITE_FLOW'"
                class="font-weight-medium"
              >{{ item.glueType +"："+ item.executorHandler }}</span>
              <span
                v-else
                class="font-weight-medium"
              >{{ resolveGlueTypeVariant(item.glueType).title }}</span>
            </template>

            <template #item.author="{ item }">
              <span class="font-weight-medium">{{ item.author }}</span>
            </template>

            <template #item.triggerStatus="{ item }">
              <VChip
                :color="resolveStatusVariant(item.triggerStatus).color"
                class="font-weight-medium"
                size="small"
              >
                {{ resolveStatusVariant(item.triggerStatus).title }}
              </VChip>
            </template>

            
            <template #item.actions="{ item }">
              <VMenu
                open-on-hover
                transition="slide-x-transition"
              >
                <template #activator="{ props }">
                  <VBtn v-bind="props">
                    操作
                  </VBtn>
                </template>

                <VList
                  :items="getMenus(item)"
                  @click:select="operClick"
                />
              </VMenu>
            </template> 

            <!-- pagination -->
            <template #bottom>
              <VDivider />
              <div class="d-flex align-center justify-sm-space-between justify-center flex-wrap gap-3 pa-5 pt-3">
                <p class="text-sm text-disabled mb-0">
                  共<span style="color: #7367f0;">&nbsp;{{ totalRows }}&nbsp;</span>条记录
                </p>
                <VPagination
                  v-model="options.page"
                  :length="Math.ceil(totalRows / options.itemsPerPage)"
                  :total-visible="$vuetify.display.xs ? 1 : Math.ceil(totalRows / options.itemsPerPage)"
                >
                  <template #prev="slotProps">
                    <VBtn
                      variant="tonal"
                      color="default"
                      v-bind="slotProps"
                      :icon="false"
                    >
                      上一页
                    </VBtn>
                  </template>

                  <template #next="slotProps">
                    <VBtn
                      variant="tonal"
                      color="default"
                      v-bind="slotProps"
                      :icon="false"
                    >
                      下一页
                    </VBtn>
                  </template>
                </VPagination>
              </div>
            </template>
          </VDataTableServer>
          <!-- SECTION -->
        </VCard>

        <VDialog
          v-model="editVisible"
          fullscreen
          :scrim="false"
          transition="dialog-bottom-transition"
        >
          <VCard>
            <div>
              <VToolbar color="primary">
                <VBtn
                  icon
                  variant="plain"
                  @click="editVisible = false"
                >
                  <VIcon
                    color="white"
                    icon="tabler-x"
                  />
                </VBtn>

                <VToolbarTitle>设置</VToolbarTitle>

                <VSpacer />

                <VToolbarItems>
                  <VBtn
                    variant="text"
                    @click="editCancelMethod"
                  >
                    取消
                  </VBtn>
                  <VBtn
                    variant="text"
                    @click="editCallMethod"
                  >
                    保存
                  </VBtn>
                </VToolbarItems>
              </VToolbar>
            </div>
            <div style="padding: 24px;block-size: 100%;overflow-y: scroll;">
              <TaskEdit
                ref="editRef"
                :curr-row="currRow"
                :add-url="addUrl"
                :update-url="updateUrl"
                :curr-option="option"
                :job-group-option="jobGroupOption"
                @refreshPage="refreshPage"
                @closeEditDialog="closeEditDialog"
              />
            </div>
          </VCard>
        </VDialog>
        
        <!-- 删除确认 -->
        <VDialog
          v-model="deleteVisible"
          width="300"
        >
          <DialogCloseBtn @click="deleteVisible = !deleteVisible" />
          <VCard title="提示">
            <VCardText> 是否确认删除？ </VCardText>
            <VCardText class="d-flex justify-end gap-3 flex-wrap">
              <VBtn
                color="secondary"
                variant="tonal"
                @click="deleteVisible = false"
              >
                取消
              </VBtn>
              <VBtn @click="deleteAgreeCmp">
                确定
              </VBtn>
            </VCardText>
          </VCard>
        </VDialog>

        <!-- 任务开始确认 -->
        <VDialog
          v-model="startVisible"
          width="300"
        >
          <DialogCloseBtn @click="startVisible = !startVisible" />
          <VCard title="提示">
            <VCardText> 是否确认开始任务？ </VCardText>
            <VCardText class="d-flex justify-end gap-3 flex-wrap">
              <VBtn
                color="secondary"
                variant="tonal"
                @click="startVisible = false"
              >
                取消
              </VBtn>
              <VBtn @click="startAgreeCmp">
                确定
              </VBtn>
            </VCardText>
          </VCard>
        </VDialog>

        <!-- 任务结束确认 -->
        <VDialog
          v-model="stopVisible"
          width="300"
        >
          <DialogCloseBtn @click="stopVisible = !stopVisible" />
          <VCard title="提示">
            <VCardText> 是否确认结束任务？ </VCardText>
            <VCardText class="d-flex justify-end gap-3 flex-wrap">
              <VBtn
                color="secondary"
                variant="tonal"
                @click="stopVisible = false"
              >
                取消
              </VBtn>
              <VBtn @click="stopAgreeCmp">
                确定
              </VBtn>
            </VCardText>
          </VCard>
        </VDialog>

        <VDialog
          v-model="execOneVisible"
          max-width="600"
          persistent 
        >
          <DialogCloseBtn @click="execOneVisible = !execOneVisible" />
          <VCard title="执行一次">
            <VCardText>
              <VRow>
                <VCol cols="12">
                  <VTextarea
                    v-model="executorParam"
                    class="lf-config-item"
                    label="任务参数"
                    clearable
                    counter
                    maxlength="255"
                    hint="请输入任务参数"
                  />
                </VCol>
                <VCol cols="12">
                  <VTextarea
                    v-model="addressList"
                    class="lf-config-item"
                    label="机器地址"
                    clearable
                    counter
                    maxlength="255"
                    hint="请输入本次执行的机器地址，为空则从任务执行器获取"
                  />
                </VCol>
              </VRow>
            </VCardText>

            <VCardText class="d-flex justify-end flex-wrap gap-3">
              <VBtn
                variant="tonal"
                color="secondary"
                @click="execOneVisible = false"
              >
                关闭
              </VBtn>
              <VBtn @click="execOneClick">
                执行
              </VBtn>
            </VCardText>
          </VCard>
        </VDialog>

        <!-- 查询日志 -->
        <VDialog
          v-model="logVisible"
          min-width="98%"
        >
          <DialogCloseBtn @click="logVisible = !logVisible" />

          <VCard>
            <VCardText>
              <TaskLogList :task-row="currRow" />
            </VCardText>
          </VCard>
        </VDialog>

        <!-- 代码编辑 -->
        <VDialog
          v-model="codeVisible"
          max-width="900"
          persistent 
        >
          <DialogCloseBtn @click="codeVisible = !codeVisible" />
          <VCard title="代码编辑器">
            <VCardText>
              <VRow>
                <VCol cols="10">
                  <VAutocomplete
                    v-model="codeVersion"
                    class="lf-config-item"
                    clearable
                    color="success"
                    label="版本回溯"
                    :items="codeVersions"
                    item-title="glueRemark"
                    item-value="glueSource"
                  />
                </VCol>
                <VCol cols="2">
                  <VBtn @click="codeInitClick">
                    初始化代码
                  </VBtn>
                </VCol>
                <VCol cols="12">
                  <Codemirror
                    ref="cmRef"
                    v-model:value="glueSource"
                    :options="cmOptions"
                    border
                    height="300"
                    width="100%"
                    @change="onChange"
                    @input="onInput"
                    @ready="onReady"
                  />
                </VCol>
                <VCol cols="12">
                  <VTextarea
                    v-model="glueRemark"
                    class="lf-config-item"
                    label="源码备注"
                    auto-grow
                    rows="1"
                    row-height="15"
                    clearable
                    counter
                    maxlength="255"
                    hint="请输入源码备注"
                  />
                </VCol>
              </VRow>
            </VCardText>

            <VCardText class="d-flex justify-end flex-wrap gap-3">
              <VBtn
                variant="tonal"
                color="secondary"
                @click="codeVisible = false"
              >
                关闭
              </VBtn>
              <VBtn @click="codeClick">
                保存
              </VBtn>
            </VCardText>
          </VCard>
        </VDialog>
      </vcol>
    </vrow>
  </section>
</template>

<style lang="scss">
.text-capitalize {
  text-transform: capitalize;
}

.user-list-name:not(:hover) {
  color: rgba(var(--v-theme-on-background), var(--v-medium-emphasis-opacity));
}
</style>
